import jsPDF from "jspdf";
import html2canvas from "html2canvas";

/* 2.0版本，新增分页符功能 */
/* author:kirk */
/*
* 使用说明
* ele:需要导出pdf的容器元素(dom节点 不是id)
* pdfFileName: 导出文件的名字 通过调用outPutPdfFn方法也可传参数改变
* type: 1下载 2批量下载
* splitClassName: 避免分段截断的类名 当pdf有多页时需要传入此参数 , 避免pdf分页时截断元素  如表格<tr class="itemClass"></tr>
* 调用方式 先 let pdf = new PdfLoader(ele, 'pdf' ,'itemClass');
* 若想改变pdf名称 pdf.outPutPdfFn(fileName);  outPutPdfFn方法返回一个promise 可以使用then方法处理pdf生成后的逻辑
* */
/* 
 breakClassName:自定义分页符类名，默认为break_page,添加改类名的标签被自动分页到下一页
 */
class PdfLoader {
    constructor(ele, pdfFileName,type , splitClassName = ".table-no-pagination,.page-break,tr,p", breakClassName = ".page-break") {
        this.ele = ele;
        this.pdfFileName = pdfFileName;
        this.type = type;
        this.splitClassName = splitClassName;
        this.breakClassName = breakClassName;
        this.A4_HEIGHT = 841.89
        this.A4_WIDTH = 540.28
        this.pageHeight = 0
        this.pageNum = 1
    };

    getPDF(resolve) {
        return new Promise((resolve, reject) => { 
            let ele = this.ele;
            ele.style.width = ' 707px';
            let pdfFileName = this.pdfFileName
            let eleW = ele.offsetWidth // 获得该容器的宽
            let eleH = ele.scrollHeight // 获得该容器的高
            let eleOffsetTop = ele.offsetTop // 获得该容器到文档顶部的距离
            let eleOffsetLeft = ele.offsetLeft // 获得该容器到文档最左的距离
            let canvas = document.createElement("canvas")
            let abs = 0
            let win_in = document.documentElement.clientWidth || document.body.clientWidth // 获得当前可视窗口的宽度（不包含滚动条）
            let win_out = window.innerWidth // 获得当前窗口的宽度（包含滚动条）
            if (win_out > win_in) {
                abs = (win_out - win_in) / 2 // 获得滚动条宽度的一半
            }
            canvas.width = eleW * 2 // 将画布宽&&高放大两倍
            canvas.height = eleH * 2
            let context = canvas.getContext("2d")
            context.scale(2, 2) // 增强图片清晰度
            context.translate(- eleOffsetLeft - abs, - eleOffsetTop)
            // html2canvas(ele, {
            //     useCORS: true, // 允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
            //     dpi: window.devicePixelRatio * 4,scale: 4
            html2canvas(ele, {height: ele.offsetHeight, width: ele.offsetWidth, scrollX: -window.pageXOffset, allowTaint: true ,useCORS: true,dpi: window.devicePixelRatio * 4,scale: 4}).then(canvas => { 
                let contentWidth = canvas.width
                let contentHeight = canvas.height
                // 一页pdf显示html页面生成的canvas高度;
                this.pageHeight = (contentWidth / this.A4_WIDTH) * this.A4_HEIGHT
                // 这样写的目的在于保持宽高比例一致 this.pageHeight/canvas.width = a4纸高度/a4纸宽度// 宽度和canvas.width保持一致
                // 未生成pdf的html页面高度
                let leftHeight = contentHeight
                // 页面偏移
                let position = 20
                // a4纸的尺寸[595,842],单位像素，html页面生成的canvas在pdf中图片的宽高
                let imgWidth = this.A4_WIDTH  // -10为了页面有右边距
                let imgHeight = ((this.A4_WIDTH) / contentWidth) * contentHeight
                let pageData = canvas.toDataURL("image/jpeg", 1.0)
                let pdf = jsPDF("", "pt", "a4");
                // 有两个高度需要区分，一个是html页面的实际高度，和生成pdf的页面高度(841.89)
                // 当内容未超过pdf一页显示的范围，无需分页
                if (leftHeight < this.pageHeight) { // 在pdf.addImage(pageData, 'JPEG', 左，上，宽度，高度)设置在pdf中显示；
                    pdf.addImage(pageData, "JPEG", 30, position, imgWidth, imgHeight)
                    // pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
                } else { // 分页
                    while (leftHeight > 0) {
                        pdf.addImage(pageData, "JPEG", 30, position, imgWidth, imgHeight)
                        leftHeight -= this.pageHeight
                        position -= this.A4_HEIGHT
                        // 避免添加空白页
                        if (leftHeight > 0) {
                            pdf.addPage()
                        }
                    }
                }
                if(this.type==1){
                    pdf.save(pdfFileName + ".pdf", {returnPromise: true}).then(() => { // 去除添加的空div 防止页面混乱
                        let doms = document.querySelectorAll('.emptyDiv')
                        for (let i = 0; i < doms.length; i++) {
                            doms[i].remove();
                        }
                    });
                    this.ele.style.height = '';
                    resolve();
                }else{
                    resolve(pdf);
                }
            })

        })
    };
    // 输出pdf
    outPutPdfFn(pdfFileName) {
        // return // 进行分割操作，当dom内容已超出a4的高度，则将该dom前插入一个空dom，把他挤下去，分割
        let target = this.ele;
        this.pageHeight = target.scrollWidth / this.A4_WIDTH * this.A4_HEIGHT;
        this.ele.style.height = 'initial';
        pdfFileName ? this.pdfFileName = pdfFileName : null;
        this.pageNum = 1; // pdf页数
        this.domEach(this.ele)
        // 异步函数，导出成功后处理交互
        return this.getPDF();
    };
    domEach(dom) {

        const breakList = dom.querySelectorAll(this.breakClassName); 
        for (let i = 0; i < breakList.length; i++) {
            debugger
            const node = breakList[i]
            // debugger
            // this.pageNum ++
            // console.log('break_page');
            // let eleBounding = this.ele.getBoundingClientRect();
            // let bound = node.getBoundingClientRect();
            // let offset2Ele = bound.top - eleBounding.top
            // // 剩余高度
            // let alreadyHeight = offset2Ele % this.pageHeight
            // let remainingHeight = this.pageHeight - alreadyHeight 
            node.style.minHeight = this.pageHeight-30 + 'px'
        }

        // const domList = document.getElementsByClassName(this.splitClassName)
        // 进行分割操作，当dom内容已超出a4的高度，则将该dom前插入一个空dom，把他挤下去，分割
        const domList = dom.querySelectorAll(this.splitClassName); 
        for (let i = 0; i < domList.length; i++) {
            
            // let node = domList[i];
            // let eleBounding = this.ele.getBoundingClientRect();
            // let bound = node.getBoundingClientRect();
            // let offset2Ele = bound.top - eleBounding.top
            // let currentPage = Math.ceil((bound.bottom - eleBounding.top) / (this.pageHeight  )); // 当前元素应该在哪一页
            // if (this.pageNum < currentPage) {
            //     debugger
            //     this.pageNum ++
            //     let divParent = node.parentNode; // 获取该div的父节点
            //     let newNode = document.createElement('div');
            //     newNode.className = 'emptyDiv';
            //     newNode.style.background = 'white';
            //     newNode.style.height = (this.pageHeight * (this.pageNum - 1) - offset2Ele + 30) + 'px'; // +30为了在换下一页时有顶部的边距
            //     newNode.style.width = '100%';
            //     let next = node.nextSibling;
            //     // 获取div的下一个兄弟节点
            //     // 判断兄弟节点是否存在
            //     if (next) { // 存在则将新节点插入到div的下一个兄弟节点之前，即div之后
            //         divParent.insertBefore(newNode, node);
            //     } else { // 不存在则直接添加到最后,appendChild默认添加到divParent的最后
            //         divParent.appendChild(newNode);
            //     }
            // }
            

            this.ele.style.height = 'initial'
            const target = this.ele
            const pageHeight =
                (target.scrollWidth / this.A4_WIDTH) * this.A4_HEIGHT
            // 获取分割dom，此处为class类名为item的dom
            // 进行分割操作，当dom内容已超出a4的高度，则将该dom前插入一个空dom，把他挤下去，分割
            let pageNum = 1 // pdf页数
            const eleBounding = this.ele.getBoundingClientRect()
            for (let i = 0; i < domList.length; i++) {
                const node = domList[i]
                const bound = node.getBoundingClientRect()
                const offset2Ele = bound.top - eleBounding.top
                const currentPage = Math.ceil(
                    (bound.bottom - eleBounding.top) / (this.pageHeight - 30 )
                ) // 当前元素应该在哪一页
                if (pageNum < currentPage) {
                    pageNum++
                    const divParent = domList[i].parentNode // 获取该div的父节点
                    const newNode = document.createElement('div')
                    newNode.className = 'emptyDiv'
                    newNode.style.background = 'white'
                    newNode.style.height =
                        pageHeight * (pageNum - 1) - offset2Ele + 30 + 'px' // +30为了在换下一页时有顶部的边距
                    newNode.style.width = '100%'
                    divParent.insertBefore(newNode, node) //在每一个节点前面插入一个空的新节点，防止内容被分割截断
                }
            }
        }

        

        // childNodes.forEach((childDom, index) => {
        //     if (this.hasClass(childDom, this.splitClassName)) {
        //         let node = childDom;
        //         let eleBounding = this.ele.getBoundingClientRect();
        //         let bound = node.getBoundingClientRect();
        //         let offset2Ele = bound.top - eleBounding.top
        //         let currentPage = Math.ceil((bound.bottom - eleBounding.top) / this.pageHeight); // 当前元素应该在哪一页
        //         if (this.pageNum < currentPage) {
        //             this.pageNum ++
        //             let divParent = childDom.parentNode; // 获取该div的父节点
        //             let newNode = document.createElement('div');
        //             newNode.className = 'emptyDiv';
        //             newNode.style.background = 'white';
        //             newNode.style.height = (this.pageHeight * (this.pageNum - 1) - offset2Ele + 30) + 'px'; // +30为了在换下一页时有顶部的边距
        //             newNode.style.width = '100%';
        //             let next = childDom.nextSibling;
        //             // 获取div的下一个兄弟节点
        //             // 判断兄弟节点是否存在
        //             if (next) { // 存在则将新节点插入到div的下一个兄弟节点之前，即div之后
        //                 divParent.insertBefore(newNode, node);
        //             } else { // 不存在则直接添加到最后,appendChild默认添加到divParent的最后
        //                 divParent.appendChild(newNode);
        //             }
        //         }
        //     }
        //     if (this.hasClass(childDom, this.breakClassName)) {
        //         debugger
        //         this.pageNum ++
        //         console.log('break_page');
        //         let eleBounding = this.ele.getBoundingClientRect();
        //         let bound = childDom.getBoundingClientRect();
        //         let offset2Ele = bound.top - eleBounding.top
        //         // 剩余高度
        //         let alreadyHeight = offset2Ele % this.pageHeight
        //         let remainingHeight = this.pageHeight - alreadyHeight + 20
        //         childDom.style.height = remainingHeight + 'px'
        //     }
        //     if (childDom.childNodes.length) {
        //         this.domEach(childDom)
        //     }
        // })
    }
    hasClass(element, cls) {
        return(`` + element.className + ``).indexOf(`` + cls + ``) > -1;
    }
}

export default PdfLoader;